/******************************************************************************
* Copyright (C) 2017, Huada Semiconductor Co.,Ltd All rights reserved.
*
* This software is owned and published by:
* Huada Semiconductor Co.,Ltd ("HDSC").
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with HDSC
* components. This software is licensed by HDSC to be adapted only
* for use in systems utilizing HDSC components. HDSC shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. HDSC is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* Disclaimer:
* HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
* REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
* ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
* WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
* WARRANTY OF NONINFRINGEMENT.
* HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
* NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
* LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
* INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
* SAVINGS OR PROFITS,
* EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
* INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
* FROM, THE SOFTWARE.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/
/******************************************************************************/
/** \file main.c
 **
 ** A detailed description is available at
 ** @link Sample Group Some description @endlink
 **
 **   - 2017-05-17  1.0  cj First version for Device Driver Library of Module.
 **
 ******************************************************************************/

/******************************************************************************
 * Include files
 ******************************************************************************/
#include <stdio.h>
#include <string.h>
#include  "stdlib.h"
#include "ddl.h"
#include "uart.h"
#include "gpio.h"
#include "i2c.h"
#include "sysctrl.h"
#include "codetab.h"
#include "ds1302.h"
#include "bt.h"
#include "flash.h"
#include "belt_time.h"
#include "can.h"
#include "dac.h"
#include "adc.h"
#include "bgr.h"
#include "adt.h"
#include "odrive.h"
// 添加这个函数  才能使用 print串口打印功能
int fputc(int ch,FILE *f)
{
    uint8_t temp[1]={ch};
		Uart_SendDataPoll(M0P_UART0,temp[0]);
    return 0;
}

uint8_t u8RxData[100] = {};  //定义 一个数组用来 存放 接收到的 串口数据 
uint8_t u8TxData[20] = {};//定义 一个数组用来 存放 准备发送到的 串口数据 
uint32_t Rx_len = 0;   //定义一个 变量  存放 当前 程序已经总共接收到多少字节数据
int time_uart = 0;   //定义接收 超时 变量
	
char ID_num = 0;  //全局 板号 ID 定义
	
char motor_dir = 0;   //上位机控制电机的方向
char motor_speed = 0;   //上位机控制电机的速度
unsigned char outputdata;  //上位机控制Led的状态
	
unsigned char inputdata;  //当前的感应器的状态
	
	
	
///< 时钟初始化
void App_ClkCfg(void)
{
//   stc_sysctrl_pll_cfg_t stcPLLCfg;    
//    
//    ///< 切换时钟前（根据外部高速晶振）设置XTH频率范围,配置晶振参数，使能目标时钟，此处为SYSTEM_XTH = 32MHz
//    Sysctrl_SetXTHFreq(SysctrlXthFreq4_8MHz);
//    Sysctrl_XTHDriverCfg(SysctrlXtalDriver1);
//    Sysctrl_SetXTHStableTime(SysctrlXthStableCycle16384);
//    Sysctrl_ClkSourceEnable(SysctrlClkXTH, TRUE);
//    delay1ms(10);
//    
//    stcPLLCfg.enInFreq    = SysctrlPllInFreq6_12MHz;    //XTH 8MHz
//    stcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  //PLL 输出
//    stcPLLCfg.enPllClkSrc = SysctrlPllXthXtal;              //输入时钟源选择RCH
//    stcPLLCfg.enPllMul    = SysctrlPllMul6;             //8MHz x 6 = 48MHz
//    Sysctrl_SetPLLFreq(&stcPLLCfg); 
//    
//    ///< 当使用的时钟源HCLK大于24M：设置FLASH 读等待周期为1 cycle(默认值也为1 cycle)
//    Flash_WaitCycle(FlashWaitCycle1);    

//    ///< 使能PLL
//    Sysctrl_ClkSourceEnable(SysctrlClkPLL, TRUE);    
//    ///< 时钟切换到PLL
//    Sysctrl_SysClkSwitch(SysctrlClkPLL);

stc_sysctrl_pll_cfg_t stcPLLCfg;    
    
    ///< RCH时钟不同频率的切换，需要先将时钟切换到RCL
    Sysctrl_SetRCLTrim(SysctrlRclFreq32768);
    Sysctrl_SetRCLStableTime(SysctrlRclStableCycle64);
    Sysctrl_ClkSourceEnable(SysctrlClkRCL, TRUE);
    Sysctrl_SysClkSwitch(SysctrlClkRCL);
    
    ///< 加载目标频率的RCH的TRIM值
    Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);
    ///< 使能RCH
    Sysctrl_ClkSourceEnable(SysctrlClkRCH, TRUE);
    
    stcPLLCfg.enInFreq    = SysctrlPllInFreq4_6MHz;     //RCH 4MHz
    stcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  //PLL 输出
    stcPLLCfg.enPllClkSrc = SysctrlPllRch;              //输入时钟源选择RCH
    stcPLLCfg.enPllMul    = SysctrlPllMul12;            //4MHz x 12 = 48MHz
    Sysctrl_SetPLLFreq(&stcPLLCfg); 
    
    ///< 当使用的时钟源HCLK大于24M：设置FLASH 读等待周期为1 cycle(默认值也为1 cycle)
    Flash_WaitCycle(FlashWaitCycle1);    
    
    ///< 使能PLL
    Sysctrl_ClkSourceEnable(SysctrlClkPLL, TRUE);
    ///< 时钟切换到PLL
    Sysctrl_SysClkSwitch(SysctrlClkPLL);
		
}

//串口配置
void App_UartCfg(void)
{
    stc_uart_cfg_t    stcCfg;   //定义一个stc_uart_cfg_t（uart）类型的 变量

	 DDL_ZERO_STRUCT(stcCfg);   //将变量初始化为0
    
    ///< 开启外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);///<使能uart0模块时钟
    
    ///<UART Init
    stcCfg.enRunMode        = UartMskMode1;          ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;           ///<1bit停止位
    stcCfg.enMmdorCk        = UartMskDataOrAddr;           ///<无检验
	
    stcCfg.stcBaud.u32Baud  = 9600;                  ///<波特率9600	
    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;       ///<通道采样分频配置
    stcCfg.stcBaud.u32Pclk  = Sysctrl_GetPClkFreq(); ///<获得外设时钟（PCLK）频率值
	
    Uart_Init(M0P_UART0, &stcCfg);                   ///<串口初始化
    
    ///<UART中断使能
    Uart_ClrStatus(M0P_UART0,UartRC);                ///<清除接收请求
    Uart_ClrStatus(M0P_UART0,UartTC);                ///<清除发送请求
    Uart_EnableIrq(M0P_UART0,UartRxIrq);             ///<使能串口接收中断IRQ
  //  Uart_EnableIrq(M0P_UART0,UartTxIrq);             ///<使能串口发送中断    
    EnableNvic(UART0_2_IRQn, IrqLevel3, TRUE);       ///<配置串口中断优先级

}



//串口引脚配置
void App_PortInit(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    
    DDL_ZERO_STRUCT(stcGpioCfg);
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟
    
    ///<TX
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA, GpioPin14, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin14, GpioAf2);          //配置PA14 端口为URART1_TX
    
    ///<RX
    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(GpioPortA, GpioPin13, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin13, GpioAf2);          //配置PA13 端口为URART1_RX
}



//Timer0配置初始化
void App_Timer0Cfg(uint16_t u16Period)
{
    uint16_t                  u16ArrValue;
    uint16_t                  u16CntValue;
    stc_bt_mode0_cfg_t     stcBtBaseCfg;
    
    DDL_ZERO_STRUCT(stcBtBaseCfg);
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
    
    stcBtBaseCfg.enWorkMode = BtWorkMode0;                  //定时器模式
    stcBtBaseCfg.enCT       = BtTimer;                      //定时器功能，计数时钟为内部PCLK
    stcBtBaseCfg.enPRS      = BtPCLKDiv64;                 //PCLK/64
    stcBtBaseCfg.enCntMode  = Bt16bitArrMode;               //自动重载16位计数器/定时器
    stcBtBaseCfg.bEnTog     = FALSE;
    stcBtBaseCfg.bEnGate    = FALSE;
    stcBtBaseCfg.enGateP    = BtGatePositive;
    Bt_Mode0_Init(TIM0, &stcBtBaseCfg);                     //TIM0 的模式0功能初始化
    
    u16ArrValue = 0x10000 - u16Period;     // 65536 -60000 = 5536    
    Bt_M0_ARRSet(TIM0, u16ArrValue);                        //设置重载值(ARR = 0x10000 - 周期)
    
	  u16CntValue = 0x10000 - u16Period;   // 初始计数为 5536  计数到 0xffff  重载 ARR（5536）
    Bt_M0_Cnt16Set(TIM0, u16CntValue);                      //设置计数初值
    
    Bt_ClearIntFlag(TIM0,BtUevIrq);                         //清中断标志   
    Bt_Mode0_EnableIrq(TIM0);                               //使能TIM0中断(模式0时只有一个中断)
    EnableNvic(TIM0_IRQn, IrqLevel3, TRUE);                 //TIM0中断使能
		Bt_M0_Run(TIM0);        //TIM0 运行。
}
/*******************************************************************************
 * TIM0中断服务函数
 ******************************************************************************/
void Tim0_IRQHandler(void)
{
    static uint8_t i;
    
    //Timer0 模式0 溢出中断
    if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))
    { 
        Bt_ClearIntFlag(TIM0,BtUevIrq); //中断标志清零
				
				Bt_M0_Stop(TIM0);		 //停止	Timer0 计数
			
			//  printf("%d \r\n",1);
			
				Uart_DisableIrq(M0P_UART0, UartRxIrq);///< 关闭 UART 接收
		//		u8RxFlg = 1;			
    }
}

///< ADC采样端口初始化
void App_AdcPortInit(void)
{    
   ///< 开启 GPIO外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    
    Gpio_SetAnalogMode(GpioPortA, GpioPin0);        //PA00 (AIN0)
		Gpio_SetAnalogMode(GpioPortA, GpioPin1);        //PA00 (AIN0)
		Gpio_SetAnalogMode(GpioPortA, GpioPin2);        //PA00 (AIN0)
		Gpio_SetAnalogMode(GpioPortA, GpioPin3);        //PA00 (AIN0)
}
///< ADC模块 初始化
void App_AdcInit(void)
{
    stc_adc_cfg_t              stcAdcCfg;

    DDL_ZERO_STRUCT(stcAdcCfg);
    
    ///< 开启ADC/BGR外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
    
    Bgr_BgrEnable();                                        ///< 开启BGR
    
    ///< ADC 初始化配置
    stcAdcCfg.enAdcMode         = AdcSglMode;               ///<采样模式-单次
    stcAdcCfg.enAdcClkDiv       = AdcMskClkDiv8;            ///<采样分频-4
    stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle12Clk;     ///<采样周期数-12
    stcAdcCfg.enAdcRefVolSel    = AdcMskRefVolSelAVDD;  ///<参考电压选择-AVDD
    stcAdcCfg.enAdcOpBuf        = AdcMskBufDisable;         ///<OP BUF配置-关
    stcAdcCfg.enInRef           = AdcMskInRefDisable;        ///<内部参考电压使能-关
    stcAdcCfg.enAdcAlign        = AdcAlignRight;            ///<转换结果对齐方式-右
    Adc_Init(&stcAdcCfg);

}

short int  u32AdcRestult[4] ; //定义 4个变量 存放 AD值
///< ADC 单次采样
void App_AdcSglCfg(void)
{

	

	
    ///< 配置单次采样通道
    Adc_CfgSglChannel(AdcExInputCH0);   
    ///< 启动单次采样
	
		Gpio_WriteOutputIO(GpioPortB, GpioPin7, TRUE);  //发射二极管 发光
    Adc_SGL_Start(); 	                              //启动AD采集
		while(FALSE == Adc_GetIrqStatus(AdcMskIrqSgl))  //直到采集完成
		{

		}	
		
		Gpio_WriteOutputIO(GpioPortB, GpioPin7, FALSE); //关闭二极管 发光
		
		u32AdcRestult[0] = Adc_GetSglResult(); //获取单片机的AD数据
		Adc_ClrIrqStatus(AdcMskIrqSgl); //清除AD采集完成状态	以给下次采集
		if(ID_num  == 0)
		{
			if(u32AdcRestult[0] > 50) inputdata |= 1<<0;
			else   inputdata &= ~(1<<0);
			if(u32AdcRestult[0] > 50) inputdata |= 1<<1;
			else   inputdata &= ~(1<<1);
		}
		else
		{
			if(u32AdcRestult[0] < 50) inputdata |= 1<<0;
			else   inputdata &= ~(1<<0);
			if(u32AdcRestult[0] < 50) inputdata |= 1<<1;
			else   inputdata &= ~(1<<1);
		}
		
		
		///< 配置单次采样通道
    Adc_CfgSglChannel(AdcExInputCH1);   
    ///< 启动单次采样
	
		Gpio_WriteOutputIO(GpioPortB, GpioPin6, TRUE);  //发射二极管 发光
    Adc_SGL_Start(); 	                              //启动AD采集
		while(FALSE == Adc_GetIrqStatus(AdcMskIrqSgl))  //直到采集完成
		{

		}	
		
		Gpio_WriteOutputIO(GpioPortB, GpioPin6, FALSE); //关闭二极管 发光
		u32AdcRestult[1] = Adc_GetSglResult(); //获取单片机的AD数据
		Adc_ClrIrqStatus(AdcMskIrqSgl); //清除AD采集完成状态	以给下次采集

		
		
				///< 配置单次采样通道
    Adc_CfgSglChannel(AdcExInputCH2);   
    ///< 启动单次采样
	
		Gpio_WriteOutputIO(GpioPortB, GpioPin5, TRUE);  //发射二极管 发光
    Adc_SGL_Start(); 	                              //启动AD采集
		while(FALSE == Adc_GetIrqStatus(AdcMskIrqSgl))  //直到采集完成
		{

		}	
		
		Gpio_WriteOutputIO(GpioPortB, GpioPin5, FALSE); //关闭二极管 发光
		
		u32AdcRestult[2] = Adc_GetSglResult(); //获取单片机的AD数据
		Adc_ClrIrqStatus(AdcMskIrqSgl); //清除AD采集完成状态	以给下次采集
		
		if(ID_num  == 0)
		{
			if(u32AdcRestult[2] > 50) inputdata |= 1<<2;
			else   inputdata &= ~(1<<2);
			if(u32AdcRestult[2] > 50) inputdata |= 1<<3;
			else   inputdata &= ~(1<<3);
		}
		else
		{
			if(u32AdcRestult[2] < 50) inputdata |= 1<<2;
			else   inputdata &= ~(1<<2);
			if(u32AdcRestult[2] < 50) inputdata |= 1<<3;
			else   inputdata &= ~(1<<3);
		}
		
		
		
				///< 配置单次采样通道
    Adc_CfgSglChannel(AdcExInputCH3);   
    ///< 启动单次采样
	
		Gpio_WriteOutputIO(GpioPortB, GpioPin4, TRUE);  //发射二极管 发光
    Adc_SGL_Start(); 	                              //启动AD采集
		while(FALSE == Adc_GetIrqStatus(AdcMskIrqSgl))  //直到采集完成
		{

		}	
		
		Gpio_WriteOutputIO(GpioPortB, GpioPin4, FALSE); //关闭二极管 发光
		
		u32AdcRestult[3] = Adc_GetSglResult(); //获取单片机的AD数据
		Adc_ClrIrqStatus(AdcMskIrqSgl); //清除AD采集完成状态	以给下次采集	
		
	
								 

}

void Gpio_Cfg(void)
{
	  stc_gpio_cfg_t stcGpioCfg;
    
    DDL_ZERO_STRUCT(stcGpioCfg);
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟
    	
	  stcGpioCfg.enDir = GpioDirOut;                           ///< 端口方向配置->输出    
    stcGpioCfg.enOD = GpioOdDisable;                          ///< 开漏输出
    stcGpioCfg.enPu = GpioPuEnable;                          ///< 端口上拉配置->使能
    stcGpioCfg.enPd = GpioPdDisable;                         ///< 端口下拉配置->禁止
    
    Gpio_Init(GpioPortB,GpioPin7,&stcGpioCfg);
		Gpio_Init(GpioPortB,GpioPin6,&stcGpioCfg);
		Gpio_Init(GpioPortB,GpioPin5,&stcGpioCfg);
		Gpio_Init(GpioPortB,GpioPin4,&stcGpioCfg);
}



#define RCLK_PORT        GpioPortC
#define RCLK_PIN         GpioPin13
#define SRCLK_PORT        GpioPortB
#define SRCLK_PIN         GpioPin9
#define SER_PORT        GpioPortB
#define SER_PIN         GpioPin8

#define RCLK_HIGH      Gpio_WriteOutputIO(RCLK_PORT, RCLK_PIN,TRUE);
#define RCLK_LOW      Gpio_WriteOutputIO(RCLK_PORT, RCLK_PIN,FALSE);

#define SRCLK_HIGH      Gpio_WriteOutputIO(SRCLK_PORT, SRCLK_PIN,TRUE);
#define SRCLK_LOW      Gpio_WriteOutputIO(SRCLK_PORT, SRCLK_PIN,FALSE);

#define SER_HIGH      Gpio_WriteOutputIO(SER_PORT, SER_PIN,TRUE);
#define SER_LOW      Gpio_WriteOutputIO(SER_PORT, SER_PIN,FALSE);

void HC595_Driver(unsigned char OutData)
{
	unsigned char i; //发送数据时做循环使用临时变量
    for (i = 0; i < 8; i++) //将16位数据按位发送
    {
        SRCLK_LOW;  //时钟线低电平
    if ((OutData & 0x80) == 0x80) //判断数据高低位
    {
        SER_HIGH; //发送数据高位
    }
    else
    {
        SER_LOW; //发送数据低位
    }
    OutData = OutData << 1; //数据左移1位
    SRCLK_HIGH;          //时钟线高电平
    }
    //上升沿输出数据
    RCLK_LOW;
    RCLK_HIGH;
}

static void lightInit(void)
{
   stc_gpio_cfg_t stcGpioCfg;
    
    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
    
	
    stcGpioCfg.enDir = GpioDirOut;                           ///< 端口方向配置->输出    
    stcGpioCfg.enOD = GpioOdDisable;                          ///< 开漏输出
    stcGpioCfg.enPu = GpioPuEnable;                          ///< 端口上拉配置->使能
    stcGpioCfg.enPd = GpioPdDisable;                         ///< 端口下拉配置->禁止

    Gpio_WriteOutputIO(RCLK_PORT, RCLK_PIN, TRUE);   

    Gpio_WriteOutputIO(SRCLK_PORT, SRCLK_PIN, TRUE);   

    Gpio_WriteOutputIO(SER_PORT, SER_PIN, TRUE);   
	

    ///< GPIO IO端口初始化
    Gpio_Init(RCLK_PORT, RCLK_PIN, &stcGpioCfg);
	
	  Gpio_Init(SRCLK_PORT, SRCLK_PIN, &stcGpioCfg);
		Gpio_Init(SER_PORT, SER_PIN, &stcGpioCfg);
	
}


//Timer1 配置  PWM 输出
void App_Timer1Cfg(uint16_t u16Period, uint16_t u16CHxACompare)
{
    uint16_t                   u16CntValue;
    uint8_t                    u8ValidPeriod;
    stc_bt_mode23_cfg_t        stcBtBaseCfg;
    stc_bt_m23_compare_cfg_t   stcBtPortCmpCfg;
    stc_bt_m23_adc_trig_cfg_t  stcBtTrigAdc;
    stc_bt_m23_dt_cfg_t        stcBtDeadTimeCfg;
    
    DDL_ZERO_STRUCT(stcBtBaseCfg);
    DDL_ZERO_STRUCT(stcBtPortCmpCfg);
    DDL_ZERO_STRUCT(stcBtTrigAdc);
    DDL_ZERO_STRUCT(stcBtDeadTimeCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE);   //Base Timer外设时钟使能      
        
    stcBtBaseCfg.enWorkMode    = BtWorkMode2;              ///< 锯齿波模式
    stcBtBaseCfg.enCT          = BtTimer;                  //定时器功能，计数时钟为内部PCLK
	stcBtBaseCfg.enPRS         = BtPCLKDiv4;                //PCLK   定时器按照 48MHZ/4 =12MHZ 的频率去计数
    //stcBtBaseCfg.enCntDir    = BtCntUp;                  //向上计数，在三角波模式时只读
    stcBtBaseCfg.enPWMTypeSel  = BtIndependentPWM;       /////< 独立PWM输出
    stcBtBaseCfg.enPWM2sSel    = BtSinglePointCmp;         //单点比较功能
    stcBtBaseCfg.bOneShot      = FALSE;                    //循环计数
    stcBtBaseCfg.bURSSel       = FALSE;                    //上下溢更新
    
    Bt_Mode23_Init(TIM1, &stcBtBaseCfg);                   //TIM0 的模式23功能初始化
    
    Bt_M23_ARRSet(TIM1, u16Period, TRUE);                  //设置重载值,并使能缓存

    Bt_M23_CCR_Set(TIM1, BtCCR0A, u16CHxACompare);         //设置比较值A,(PWM互补模式下只需要设置比较值A)
    
    stcBtPortCmpCfg.enCH0ACmpCtrl   = BtPWMMode2;          //OCREFA输出控制OCMA:PWM模式2
    stcBtPortCmpCfg.enCH0APolarity  = BtPortPositive;      //正常输出
    stcBtPortCmpCfg.bCh0ACmpBufEn   = TRUE;                //A通道缓存控制
    stcBtPortCmpCfg.enCh0ACmpIntSel = BtCmpIntNone;        //A通道比较控制:无
    
    
    Bt_M23_PortOutput_Cfg(TIM1, &stcBtPortCmpCfg);         //比较输出端口配置
    

    
    u16CntValue = 0;
    
    Bt_M23_Cnt16Set(TIM1, u16CntValue);                    //设置计数初值
		
		Bt_M23_EnPWM_Output(TIM1, FALSE, FALSE);   //使能PWM输出功能
		
	  Bt_M23_Run(TIM1);                          //TIM1 运行。
     
}

#define belt_dir_PORT        GpioPortC
#define belt_dir_PIN         GpioPin14

#define belt_break_PORT        GpioPortC
#define belt_break_PIN         GpioPin15
//MOTOR 控制端口初始化
void Motor_Cfg(void)
{
	   stc_gpio_cfg_t stcGpioCfg;
	
     DDL_ZERO_STRUCT(stcGpioCfg);
    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
    
		stcGpioCfg.enDir  = GpioDirOut;
    //PA00设置为TIM1_CHA
    Gpio_Init(GpioPortA, GpioPin6, &stcGpioCfg);  //
    Gpio_SetAfMode(GpioPortA,GpioPin6,GpioAf4);   // pwm引脚
	
	
		
    stcGpioCfg.enDir = GpioDirOut;                           ///< 端口方向配置->输出    
    stcGpioCfg.enPu = GpioPuEnable;                          ///< 端口上拉配置->使能
    stcGpioCfg.enPd = GpioPdDisable;                         ///< 端口下拉配置->禁止
	



    ///< GPIO IO端口初始化
    Gpio_Init(belt_dir_PORT, belt_dir_PIN, &stcGpioCfg);
	
	  Gpio_Init(belt_break_PORT, belt_break_PIN, &stcGpioCfg);
		
		
    Gpio_WriteOutputIO(belt_dir_PORT, belt_dir_PIN, TRUE);     //BREAK 引脚

    Gpio_WriteOutputIO(belt_break_PORT, belt_break_PIN, FALSE);    //方向引脚

}

void set_pwm_baifenbi(unsigned char  speed)  //speed 0~100
{
	 Bt_M23_CCR_Set(TIM1, BtCCR0A, speed*12);  
}

#define belt_stop          {Bt_M23_EnPWM_Output(TIM1, FALSE, FALSE); Gpio_WriteOutputIO(belt_break_PORT, belt_break_PIN,FALSE);}
#define belt_left_start    {Bt_M23_EnPWM_Output(TIM1, TRUE, FALSE);Gpio_WriteOutputIO(belt_break_PORT, belt_break_PIN,TRUE);Gpio_WriteOutputIO(belt_dir_PORT, belt_dir_PIN,FALSE); }
#define belt_right_start   {Bt_M23_EnPWM_Output(TIM1, TRUE, FALSE);Gpio_WriteOutputIO(belt_break_PORT, belt_break_PIN,TRUE);Gpio_WriteOutputIO(belt_dir_PORT, belt_dir_PIN,TRUE);}
void motor_dirver(unsigned char  dir , unsigned char speed)
{
	
	if(dir == 0) belt_stop
	else if(dir == 1)belt_left_start
	else  belt_right_start
		
	set_pwm_baifenbi(speed);	
	
}


void send_tx_Data(uint8_t * data,int len)
{
	while(len --)
	{
		Uart_SendDataPoll(M0P_UART0,*data);
    data ++;
	}
}



#define ID1_PORT        GpioPortB
#define ID1_PIN         GpioPin2
#define ID2_PORT        GpioPortB
#define ID2_PIN         GpioPin10
#define ID3_PORT        GpioPortB
#define ID3_PIN         GpioPin11
#define ID4_PORT        GpioPortB
#define ID4_PIN         GpioPin12

void ID_PORT_INIT() // ID检测端口  初始化
{
	stc_gpio_cfg_t stcGpioCfg;
    
    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
    
	
    stcGpioCfg.enDir = GpioDirIn;                           ///< 端口方向配置->输出    
    stcGpioCfg.enOD = GpioOdDisable;                          ///< 开漏输出
    stcGpioCfg.enPu = GpioPuEnable;                          ///< 端口上拉配置->使能
    stcGpioCfg.enPd = GpioPdDisable;                         ///< 端口下拉配置->禁止  

    ///< GPIO IO端口初始化
  Gpio_Init(ID1_PORT, ID1_PIN, &stcGpioCfg);
	Gpio_Init(ID2_PORT, ID2_PIN, &stcGpioCfg);
	Gpio_Init(ID3_PORT, ID3_PIN, &stcGpioCfg);
	Gpio_Init(ID4_PORT, ID4_PIN, &stcGpioCfg);

}



void Id_check() // ID检测
{
	if(Gpio_GetInputIO(ID1_PORT, ID1_PIN) == FALSE) ID_num |= (1<< 0);
	else  ID_num &= ~(1<< 0);
	
	if(Gpio_GetInputIO(ID2_PORT, ID2_PIN) == FALSE) ID_num |= (1<< 1);
	else  ID_num &= ~(1<< 1);
	
	if(Gpio_GetInputIO(ID3_PORT, ID3_PIN) == FALSE) ID_num |= (1<< 2);
	else  ID_num &= ~(1<< 2);
	
	if(Gpio_GetInputIO(ID4_PORT, ID4_PIN) == FALSE) ID_num |= (1<< 3);
	else  ID_num &= ~(1<< 3);
				
}



unsigned char comm_count = 0;  //通信计数
	
uint32_t time_100ms = 0;
uint32_t time_10ms = 0;
uint32_t time_1ms = 0;
uint32_t time_500ms = 0;

unsigned char leftbeep = 0;
unsigned char rightbeep = 0;
unsigned char color_cnt = 0;

unsigned char leftbeep_flag = 0;
unsigned char rightbeep_flag = 0;

int32_t main(void)
{     
///< 时钟配置，配置时钟12mHz
    App_ClkCfg();
	
	   
    App_PortInit(); //串口引脚配置 
		Sysctrl_SetFunc(SysctrlSWDUseIOEn, 1); //启动swd io  屏蔽下载功能才可以使用其他功能（如串口
		App_UartCfg();//串口配置
	
	
	  ID_PORT_INIT(); //初始化 ID端口
		Id_check() ;//ID检测
	
		App_AdcPortInit();
	  App_AdcInit();///< ADC模块 初始化    
   	
		Gpio_Cfg(); //初始化通用 输出
	
		lightInit(); //初始化 RGB灯的控制端口
	
	  HC595_Driver(0x77);  //RGB灯控制
	
		Motor_Cfg();
		App_Timer1Cfg(1200, 600);         //Timer1 配置:周期 1200(10K); 通道A比较值600（占空比50%）;  控制电机PWM端口初始化
	

		
		SysTick_Iint();
		
    while(1)
    {

		if(time_10ms  >10)
			{
				time_10ms =0;		  
				App_AdcSglCfg(); ///< ADC 单次采样
				

			}
		
				
	/*   解析  串口接收的数据  */		
			if(Rx_len > 0 )  //如果接收到数据
			{
				if(time_uart - HAL_GetTick()> 100 )  //串口接收到数据后  已经有100ms没有接收到新数据了 ， 证明已经接收完一帧数据
				{			
					//开始解析 程序接收到的这帧数据					
					if(u8RxData[0] == 0xaa)  //当前接收到这帧数据 的 第一个字节为 0xaa
					{
						if(u8RxData[Rx_len -1] == 0x2f)  //当前接收到这帧数据 的 最后一个字节为 0x2f
						{		
                 //开始校验数据 的校验和是否 一致							
								char sum = 0;
								for (int i = 1; i < Rx_len-2; i++) //从第二个字节累加到最后倒数第二个字节
								{
									sum += u8RxData[i];
								}
								
								if(u8RxData[Rx_len-2] == sum)  //判断 累加和（sum）  和 当前帧的倒数第二个字节（u8RxData[Rx_len-2]）是否 相等
								{
									comm_count = 0; //复位通信计数
									
									motor_dir = u8RxData[2];  //改变电机运行方向  停止=0  左=1  右=2									
									motor_speed = u8RxData[3]; //改变电机运行速度  0 -100
									
									if(u8RxData[4] & 0x80) rightbeep = 1;
									else rightbeep = 0;
									if(u8RxData[4] & 0x08) leftbeep = 1;
									else leftbeep = 0;
									
									color_cnt = u8RxData[4] & 0x77; //改变输出状态																	
								}
						}
					}
					Rx_len = 0;			
				}				
			}
		
/*     //解析结束                   */
			
			if(time_1ms - HAL_GetTick() > 1)
			{
				time_1ms = HAL_GetTick();
				time_100ms++;
				time_10ms ++;
				time_500ms++;
				
				HC595_Driver(outputdata);  //输出控制
			}
			
			
			if(time_500ms >1000)
			{
				time_500ms = 0;
				
				if(rightbeep)
				{		
					rightbeep_flag = ~ rightbeep_flag;
					if(rightbeep_flag)
						outputdata |= 0x80;
					else
						outputdata &= ~(0x80); 
				}
				else  
					outputdata &= ~(0x80); 
				
				if(leftbeep)
				{		
					leftbeep_flag = ~ leftbeep_flag;
					if(leftbeep_flag)
						outputdata |= 0x08;
					else
						outputdata &= ~(0x08); 
				}
				else  outputdata &= ~(0x08); 
								
			}
			
			/* 下面程序为   每 100 毫秒 发送一次数据 给上位机 */
			if(time_100ms  >100)
			{
				time_100ms =0;
				
				outputdata = color_cnt;				
				
				HC595_Driver(outputdata);  //输出控制
				motor_dirver(motor_dir,motor_speed);
				
					
				if(comm_count > 100)
				{
					 motor_dir = 0 ;
					 outputdata = 0;
				}
				else
				{
					comm_count ++;
				}
				
				
				u8TxData[0] = 0XAA;
				u8TxData[1] = 0X01;
				u8TxData[2] = motor_dir;  //电机状态  停止=0  左=1  右=2
				u8TxData[3] = inputdata;  //开关输入状态    1为On  0为off 
				u8TxData[4] = outputdata;  //输出状态
	      for(int i = 0;i<4;i++)
				{			
					u8TxData[5+i*2] = u32AdcRestult[i] >> 8;
					u8TxData[6+i*2] = u32AdcRestult[i] & 0xff;
				}
				

				char sum = 0;
				for (int i = 1; i < 13; i++)
				{
						sum = sum + u8TxData[i];
				}
				u8TxData[13] = sum;
				u8TxData[14] = 0x2f;
		  	send_tx_Data(u8TxData,15);
				
			}		
		}
}


///< UART1 中断服务函数
void Uart0_IRQHandler(void)
{
    if(TRUE == Uart_GetStatus(M0P_UART0, UartRC))  //如果接收数据
    {
        Uart_ClrStatus(M0P_UART0, UartRC);        //清除接收中断状态
        u8RxData[Rx_len] = Uart_ReceiveData(M0P_UART0);	  	 //把	当前接收到的数据存放到   u8RxData数组里面
				if(Rx_len <99 )   //如果总共接收到的数据没有超过100个
				    Rx_len = Rx_len + 1 ;    //计数加1
				
				  time_uart = HAL_GetTick();  //将当前系统时刻 赋值给 超时变量

    }

}



